package com.alibaba.citrus.cr.mn.order.center.facade.service.impl;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.enums.ordercenter.ForecastOrderTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.lock.SaleRedisLock;
import com.alibaba.citrus.cr.common.util.ObjectNullUtil;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.nvlToEmptyUtils;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.ForecastOrderBizDomainService;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.QueryForecastLineResponseToResponseConvertor;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.QueryForecastResponseToResponseConvertor;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.mnordercenter.forecastordergroup.service.ForecastOrderGroupService;
import com.epoch.app.mnordercenter.model.dto.*;
import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.alibaba.citrus.cr.mn.order.center.common.constants.RedisLockConstants.*;

@Service
@Primary
public class ForecastOrderGroupServiceImpl implements ForecastOrderGroupService {

	private static final Log log = Log.getLogger(ForecastOrderBizServiceImpl.class);

	// 初始化一盘货的预报订单类型集合
	private static final List<String> forecastOrderTypeList = Lists.newArrayList(ForecastOrderTypeEnum.GROUP_FORECAST.getCode());

	@Resource
	private ForecastOrderBizDomainService forecastOrderBizDomainService;

	@Override
	@FacadeInvoker
	public Result<ForecastBizAsyncResponse> batchCreate(ForecastOrderBizBatchCreateRequest request) {
		// 设置F-B一盘货预报订单缺省值
		List<CreateForecastDTO> createForecastDTOs = request.getCreateForecastOrderDTOS();
		log.info("createForecastDTOs参数:{}", JSON.toJSONString(createForecastDTOs));
		AssertUtils.isTrue(CollectionUtils.isEmpty(createForecastDTOs), "OC-01-001-01-15-001", "单据列表");

		createForecastDTOs.forEach(createForecastDTO -> {
			// 设置订单类别编码缺省值：200集团
			createForecastDTO.setOrderCategoryCode(OrderCategoryEnum.GROUP.getCode());
			// 设置订单类型编码缺省值：ZQT集团预报订单
//			if(StringUtils.isBlank(createForecastDTO.getSalesOrderType())) {
//				createForecastDTO.setSalesOrderType(ForecastOrderTypeEnum.GROUP_FORECAST.getCode());
//			}
		});

		return buildSuccessResult(forecastOrderBizDomainService.batchCreate(request));
	}

	@Override
	@FacadeInvoker
	public Result<ForecastBizSyncResponse> create(ForecastOrderBizCreateRequest request) {
		log.info("ForecastOrderGroupServiceImpl#create request={}", JSON.toJSONString(request));
		String lockKey = FORECAST_ORDER_GROUP_PREFIX + request.getReqNo();
		log.info("ForecastOrderGroupServiceImpl#create lockKey={}", lockKey);
		try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
			if (!lock.lock()) {
				log.error("ForecastOrderGroupServiceImpl#create 分布式锁获取失败 lockKey={}", lockKey);
				return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
			}
			CreateForecastDTO createForecastDTO = request.getCreateForecastOrderDTO();
			AssertUtils.isTrue(createForecastDTO == null, "OC-01-001-01-15-001", "预报订单");
			createForecastDTO.setOrderCategoryCode(OrderCategoryEnum.GROUP.getCode());
			return forecastOrderBizDomainService.create(request);
		} catch (Exception e) {
			log.error("ForecastOrderGroupServiceImpl#create error", e);
			throw e;
		}
	}

	@Override
	@FacadeInvoker
	public Result<List<CancelForecastResponseDTO>> batchCancel(CancelForecastRequest request) {
		log.info("ForecastOrderGroupServiceImpl#batchCancel request={}", JSON.toJSONString(request));
		String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
		log.info("ForecastOrderGroupServiceImpl#batchCancel lockKey={}", lockKey);
		try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
			if (!lock.lock()) {
				log.error("ForecastOrderGroupServiceImpl#batchCancel 分布式锁获取失败 lockKey={}", lockKey);
				return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
			}
			// 校验必填项，并将modifierCode转换到子对象内
			AssertUtils.isTrue(StringUtils.isBlank(request.getModifierCode()), "OC-01-001-01-15-001", "修改人工号");
			request.getCancelForecastDTOS().forEach(forecast -> forecast.setModifierCode(request.getModifierCode()));
			request.setForecastOrderTypeList(forecastOrderTypeList);
			return buildSuccessResult(forecastOrderBizDomainService.batchCancel(request));
		} catch (Exception e) {
			log.error("ForecastOrderGroupServiceImpl#batchCancel error", e);
			throw e;
		}
	}

	@Override
	@FacadeInvoker
	public Result<List<SubmitForecastResponseDTO>> batchSubmit(ForecastBizBatchSubmitRequest request) {
		request.setForecastOrderTypeList(forecastOrderTypeList);
		log.info("ForecastOrderGroupServiceImpl#batchSubmit request={}", JSON.toJSONString(request));
		String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
		log.info("ForecastOrderGroupServiceImpl#batchSubmit lockKey={}", lockKey);
		try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
			if (!lock.lock()) {
				log.error("ForecastOrderGroupServiceImpl#batchSubmit 分布式锁获取失败 lockKey={}", lockKey);
				return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
			}
			return buildSuccessResult(forecastOrderBizDomainService.batchSubmit(request));
		} catch (Exception e) {
			log.error("ForecastOrderGroupServiceImpl#batchSubmit error", e);
			throw e;
		}
	}

	@Override
	@FacadeInvoker
	public Result<ModifyForecastResponseDTO> modify(ModifyForecastRequest request) {
		ModifyForecastDTO modifyForecastDTO = request.getModifyForecastDTO();
		if(modifyForecastDTO == null){
			return Result.fail("OC-04-003-01-16-005", "预报订单修改失败");
		}

		// 判断是否只修改明细的bizFeatures字段，支持蒙维斯修改已完成状态预报单
		if (CollectionUtils.isNotEmpty(modifyForecastDTO.getModifyForecastDetailDTOS())) {
			boolean allFieldNull = false;
			List<String> ignoreFields = Lists.newArrayList("lineNum", "sourceLineNum", "bizFeatures");
			for (ModifyForecastDetailDTO item : modifyForecastDTO.getModifyForecastDetailDTOS()) {
				allFieldNull = ObjectNullUtil.isAllFieldNull(item, ignoreFields);
				if (!allFieldNull) {
					break;
				}
			}
			// 除了bizFeatures字段其他字段都为空时，打标绕过状态校验
			JSONObject features = new JSONObject();
			features.put("allFieldNull", allFieldNull);
			request.getModifyForecastDTO().setFeatures(features.toJSONString());
		}

		modifyForecastDTO.setOrderCategoryCode(OrderCategoryEnum.GROUP.getCode());
		Result<ModifyForecastResponseDTO> result = forecastOrderBizDomainService.modify(request);
		return buildSuccessResult(result);
	}

	@Override
	@FacadeInvoker
	public Result<List<ForecastOrderBizCloseResponse>> batchClose(ForecastOrderBizBatchCloseRequest request) {
		request.setForecastOrderTypeList(forecastOrderTypeList);
		log.info("ForecastOrderGroupServiceImpl#batchClose request={}", JSON.toJSONString(request));
		String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
		log.info("ForecastOrderGroupServiceImpl#batchClose lockKey={}", lockKey);
		try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
			if (!lock.lock()) {
				log.error("ForecastOrderGroupServiceImpl#batchClose 分布式锁获取失败 lockKey={}", lockKey);
				return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
			}
			return buildSuccessResult(forecastOrderBizDomainService.batchClose(request));
		} catch (Exception e) {
			log.error("ForecastOrderGroupServiceImpl#batchClose error", e);
			throw e;
		}
	}

	@Override
	@FacadeInvoker(value = "查询预报订单失败", errorCode = "OC-01-001-01-16-057")
	public Result<QueryForecastOrderResponse> query(QueryForecastRequest request) {
		request.setOrderCategoryCode(OrderCategoryEnum.GROUP.getCode());
		Result<QueryForecastResponse> queryForecastResponseResult = forecastOrderBizDomainService.query(request);
		if (!queryForecastResponseResult.isSuccess()) {
			return Result.fail(queryForecastResponseResult.getErrorCode(), queryForecastResponseResult.getMessage());
		}
		Result<QueryForecastOrderResponse> result = Result.success(QueryForecastResponseToResponseConvertor.convert(queryForecastResponseResult.getResult()));
		result.setTotal(queryForecastResponseResult.getTotal());
		return buildSuccessResult(result);
	}

	@Override
	@FacadeInvoker
	public Result<List<ForecastReplyBizModifyResponse>> batchModifyReply(ForecastReplyBizBatchModifyRequest request) {
		request.setForecastOrderTypeList(forecastOrderTypeList);
		log.info("ForecastOrderGroupServiceImpl#batchModifyReply request={}", JSON.toJSONString(request));
		String lockKey = FORECAST_ORDER_GROUP_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
		log.info("ForecastOrderGroupServiceImpl#batchModifyReply lockKey={}", lockKey);
		try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
			if (!lock.lock()) {
				log.error("ForecastOrderGroupServiceImpl#batchModifyReply 分布式锁获取失败 lockKey={}", lockKey);
				return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
			}
			return buildSuccessResult(forecastOrderBizDomainService.batchModifyReply(request));
		} catch (Exception e) {
			log.error("ForecastOrderGroupServiceImpl#batchModifyReply error", e);
			throw e;
		} finally {
			StopWatchUtils.print("ForecastOrderGroupServiceImpl#batchModifyReply");
		}
	}

	@Override
	@FacadeInvoker(value = "查询预报订单失败", errorCode = "OC-01-001-01-16-057")
	public Result<QueryB2bForecastOrderResponse> queryForecastOrderDetail(QueryForecastRequest request) {
		request.setOrderCategoryCode(OrderCategoryEnum.GROUP.getCode());
		Result<QueryForecastResponse> queryForecastResponseResult = forecastOrderBizDomainService.query(request);
		log.info("queryForecastResponseResult结果:{}",JSON.toJSONString(queryForecastResponseResult));
		if (!queryForecastResponseResult.isSuccess()) {
			return Result.fail(queryForecastResponseResult.getErrorCode(), queryForecastResponseResult.getMessage());
		}
		QueryForecastResponse queryForecastResponse = queryForecastResponseResult.getResult();
		QueryB2bForecastOrderResponse response = new QueryB2bForecastOrderResponse();
		Result<QueryB2bForecastOrderResponse> result = Result.success(response);
		if (Objects.nonNull(queryForecastResponse)) {
			// 将 QueryForecastResponse 转换为 QueryB2bForecastOrderResponse
			QueryForecastResponseToResponseConvertor.convert(response, queryForecastResponse);
			result.setTotal(1);
		}
		log.info("result最后结果:{}",JSON.toJSONString(result));
		return buildSuccessResult(result);
	}

	@Override
	@FacadeInvoker(value = "查询预报订单失败", errorCode = "OC-01-001-01-16-057")
	public Result<List<PageQueryForecastResponse>> pageQuery(PageQueryForecastRequest pageQueryForecastRequest){

		Result<List<QueryForecastResponse>> result = forecastOrderBizDomainService.pageQuery(pageQueryForecastRequest, OrderCategoryEnum.GROUP.getCode());
		if (!result.isSuccess()) {
			return Result.fail(result.getErrorCode(), result.getMessage());
		}

		Result<List<PageQueryForecastResponse>> pageResult = new Result<>();
		pageResult.setTotal(result.getTotal());
		pageResult.setSuccess(result.isSuccess());
		pageResult.setErrorCode(result.getErrorCode());
		pageResult.setMessage(result.getMessage());
		if(CollectionUtils.isNotEmpty(result.getResult())) {
			List<PageQueryForecastResponse> pageQueryForecastResponseList = result.getResult().stream().map(item -> {
				PageQueryForecastResponse pageQueryForecastResponse = new PageQueryForecastResponse();
				BeanUtils.copyProperties(item, pageQueryForecastResponse);
				pageQueryForecastResponse.setOrderStatus(String.valueOf(item.getOrderStatus()));
				pageQueryForecastResponse.setOutOrderNo(item.getOuterOrderCode());
				pageQueryForecastResponse.setValidBeginTime(item.getVaildBeginDate());
				pageQueryForecastResponse.setOutOrderNo(nvlToEmptyUtils.nvlToEmptyStr(item.getOuterOrderCode()));
				pageQueryForecastResponse.setReceiveFactoryName("");
				pageQueryForecastResponse.setReceiveStockName("");
				return pageQueryForecastResponse;
			}).collect(Collectors.toList());
			pageResult.setResult(pageQueryForecastResponseList);
		}

		return buildSuccessResult(pageResult);
	}

    @Override
	@FacadeInvoker(value = "查询预报订单失败", errorCode = "OC-01-001-01-16-057")
    public Result<List<PageQueryGroupForecastDetailResponse>> pageQueryLine(PageQueryForecastLineRequest request) {

		if(CollectionUtils.isEmpty(request.getOrderTypeCodeList())){
			List<String> orderTypeCodeList = new ArrayList<>();
			orderTypeCodeList.add(ForecastOrderTypeEnum.GROUP_FORECAST.getCode());
			request.setOrderTypeCodeList(orderTypeCodeList);
		}
		Result<List<PageQueryForecastDetailResponse>> result = forecastOrderBizDomainService.pageQueryLine(request, OrderCategoryEnum.GROUP.getCode());
		if (!result.isSuccess()) {
			return Result.fail(result.getErrorCode(), result.getMessage());
		}

		Result<List<PageQueryGroupForecastDetailResponse>> pageResult = new Result<>();
		pageResult.setTotal(result.getTotal());
		pageResult.setSuccess(result.isSuccess());
		if(CollectionUtils.isNotEmpty(result.getResult())) {
			List<PageQueryGroupForecastDetailResponse> responseList = result.getResult().stream().map(oldResponse -> {
				PageQueryGroupForecastDetailResponse newResponse = new PageQueryGroupForecastDetailResponse();
				// 将 PageQueryForecastDetailResponse 转换为 PageQueryGroupForecastDetailResponse
				QueryForecastLineResponseToResponseConvertor.convert(oldResponse, newResponse);
				return newResponse;
			}).collect(Collectors.toList());
			pageResult.setResult(responseList);
		}

		return buildSuccessResult(pageResult);
    }

	@Override
	@FacadeInvoker
	public Result<List<ForecastBizGroupResponse>> batchConfirm(ConfirmGroupReplyRequest request) {
		return buildSuccessResult(forecastOrderBizDomainService.batchGroupConfirm(request));
	}

    /**
     * 请求成功时补充Message和ErrorCode，确保出参字段都存在
     */
    private <T> Result<T> buildSuccessResult(Result<T> result) {
        StopWatch stopWatch = StopWatchUtils.clear();
        if (Objects.nonNull(stopWatch)) {
            log.info("ForecastOrderGroupServiceImpl#buildSuccessResult stopWatch.getTotalTimeSeconds()={}", stopWatch.getTotalTimeSeconds());
            log.info("ForecastOrderGroupServiceImpl#buildSuccessResult stopWatch.prettyPrint()={}", stopWatch.prettyPrint());
        }

        if (result.isSuccess()) {
            result.setMessage("");
            result.setErrorCode("");
        }
        return result;
    }

	@Override
	@FacadeInvoker(value = "查询预报订单失败", errorCode = "OC-01-001-01-16-057")
	public Result<List<QueryForecastResponse>> pageForecastOrder(PageQueryForecastRequest request) {
		Result<List<QueryForecastResponse>> listResult = forecastOrderBizDomainService.pageQuery(request, OrderCategoryEnum.COMPANY.getCode());
		if (!listResult.isSuccess()) {
			return Result.fail(listResult.getErrorCode(), listResult.getMessage());
		}
		List<QueryForecastResponse> queryForecastResponseList = listResult.getResult();
		if (CollectionUtils.isNotEmpty(queryForecastResponseList)) {
			queryForecastResponseList.forEach(forecastOrder -> {
				forecastOrder.setForecastDetailDTOS(null);
				forecastOrder.setBizFeatures(null);
			});
		}
		return buildSuccessResult(listResult);
	}

}
